home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Applications / ircle 1.5.1 / source / ircle sources / MsgWindows.p < prev   
Encoding:
Text File  |  1993-11-15  |  14.6 KB  |  615 lines  |  [TEXT/PJMM]

  1. {    ircle - Internet Relay Chat client    }
  2. {    File: MsgWindows     }
  3. {    Copyright © 1992 Olaf Titz (s_titz@ira.uka.de)    }
  4.  
  5. {    This program is free software; you can redistribute it and/or modify    }
  6. {    it under the terms of the GNU General Public License as published by    }
  7. {    the Free Software Foundation; either version 2 of the License, or    }
  8. {    (at your option) any later version.    }
  9.  
  10. {    This program is distributed in the hope that it will be useful,    }
  11. {    but WITHOUT ANY WARRANTY; without even the implied warranty of    }
  12. {    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    }
  13. {    GNU General Public License for more details.    }
  14.  
  15. {    You should have received a copy of the GNU General Public License    }
  16. {    along with this program; if not, write to the Free Software    }
  17. {    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    }
  18.  
  19. unit MsgWindows;
  20. { Deals with windows for displaying messages }
  21.  
  22. interface
  23. uses
  24.     MiscGlue, ApplBase;
  25.  
  26. const
  27.     MW_MAGIC = 'MWIN';
  28.  
  29.     C_BOLD = 2;            { Bold: ^B }
  30.     C_INVERSE = 22;            { Inverse: ^V }
  31.     C_UNDERLINE = 31;        { Underline: ^_   [ouch!] }
  32.     C_NORMAL = 15;        { Normal: ^N }
  33.  
  34. type
  35.     MWHndl = ^MWPtr;    { This gets stored in the window's refCon }
  36.     MWPtr = ^MWRec;
  37.     MWRec = record
  38.             magic: OSType;            { for checking }
  39.             w: WindowPtr;            { the Window }
  40.             whenDone: ProcPtr;        { called on closing }
  41.             hscr, vscr: ControlHandle;    { scroll bars }
  42.             t: TEHandle;                { TextEdit record }
  43.             vislines,                    { # of visible lines }
  44.             NumStyles: integer;        { used for insertion }
  45.             sty: stScrpHandle;            { ditto }
  46.         end;
  47.  
  48. var
  49.     MWActive: MWHndl;    { MWHndl of active window; or else nil }
  50.     MWdefaultFont, MWdefaultSize: integer;
  51.  
  52. procedure InitMsgWindows;
  53. { startup }
  54.  
  55. function NewMWindow (var title: string; prefSize: Rect; DoWhenDone: ProcPtr): MWHndl;
  56. { Make a new window. DoWhen done gets called when user wants to }
  57. { close window; to be declared as: procedure DoWhenDone(w:WindowPtr) }
  58.  
  59. procedure SetFontSize (window: MWHndl; font, size: integer);
  60. { Change window font/size }
  61.  
  62. procedure DeleteMWindow (window: MWHndl);
  63. { Delete window }
  64.  
  65. procedure MWMessage (window: MWHndl; var msg: string);
  66. { Display message at bottom of window }
  67.  
  68. function MWFreeMem: boolean;
  69. { Tries to free up some memory }
  70.  
  71. implementation
  72.  
  73. {$SETC ZOOM=true}
  74.  
  75. const
  76.     MW_MAXLEN = 20000;     { maximum # of chars to store }
  77.     MW_KILLEN = 5000;        { # of chars to kill if window exceeds MW_MAXLEN }
  78.  
  79.     STY_0 = sizeof(stScrpRec);
  80.     STY_1 = sizeof(ScrpSTElement);
  81.  
  82. {$IFC ZOOM}
  83. { a quick hack to deal with the zoom states }
  84. type
  85.     WStates = array[inZoomIn..inZoomOut] of Rect;
  86.     WStatesPtr = ^WStates;
  87.     WStatesHndl = ^WStatesPtr;
  88. {$ENDC}
  89.  
  90. var
  91.     glob: MWHndl;
  92.     cornerstone, screensize: rect;
  93.     flood: integer;
  94.  
  95. function EvtMW (var e: EventRecord): MWHndl;
  96.     var
  97.         w: MWHndl;
  98.     begin
  99.         w := MWHndl(GetWRefCon(WindowPtr(e.message)));
  100.         if w <> nil then
  101.             if w^^.magic <> MW_MAGIC then
  102.                 w := nil;
  103.         EvtMW := w
  104.     end;
  105.  
  106.  
  107. procedure SetWDimen (win: MWHndl; left, top, width, height, zoomstate: integer);
  108.     var
  109.         r: Rect;
  110. {$IFC ZOOM}
  111.         wp: WindowPeek;
  112.         zs: WStatesHndl;
  113. {$ENDC}
  114.     begin
  115. {$IFC ZOOM}
  116.         wp := WindowPeek(win^^.w);
  117.         zs := WStatesHndl(wp^.dataHandle);
  118. {$ENDC}
  119.         if left + width < 10 then
  120.             left := 10 - width;
  121.         win^^.vislines := (height - 20) div win^^.sty^^.scrpStyleTab[0].scrpHeight;
  122.         height := win^^.vislines * win^^.sty^^.scrpStyleTab[0].scrpHeight + 20;
  123.         SetRect(r, 3, 2, width - 17, height - 17);
  124.         win^^.t^^.destRect := r;
  125.         r.top := r.top + 1;
  126.         win^^.t^^.viewRect := r;
  127.         SetRect(r, left, top, left + width, top + height);
  128. {$IFC ZOOM}
  129.         zs^^[zoomstate] := r;
  130. {$ENDC}
  131.         MoveWindow(win^^.w, left, top, true);
  132.         SizeWindow(win^^.w, width, height, false);
  133.         EraseRect(win^^.w^.portRect);
  134.         MoveControl(win^^.hscr, -1, height - 15);
  135.         SizeControl(win^^.hscr, width - 13, 16);
  136.         MoveControl(win^^.vscr, width - 15, -1);
  137.         SizeControl(win^^.vscr, 16, height - 13);
  138.         TECalText(win^^.t);
  139.         TEPinScroll(0, 32767, win^^.t);
  140.         if win^^.t^^.nlines <= win^^.vislines then
  141.             SetCtlMax(win^^.vscr, 0)
  142.         else
  143.             SetCtlMax(win^^.vscr, win^^.t^^.nlines - win^^.vislines);
  144.         SetCtlValue(win^^.vscr, 0);
  145.         InvalRect(win^^.w^.portRect);
  146.         ShowWindow(win^^.w);
  147.         SelectWindow(win^^.w);
  148.     end;
  149.  
  150. procedure vscroll (o, n: integer);
  151.     begin
  152.         SetCtlValue(glob^^.vscr, o - n);
  153.         TEPinScroll(0, n * glob^^.sty^^.scrpStyleTab[0].scrpHeight, glob^^.t);
  154.     end;
  155. procedure Vscrolling (cc: ControlHandle; part: integer);
  156.     begin
  157.         case part of
  158.             inPageUp: 
  159.                 vscroll(GetCtlValue(glob^^.vscr), glob^^.vislines - 1);
  160.             inPageDown: 
  161.                 vscroll(GetCtlValue(glob^^.vscr), 1 - glob^^.vislines);
  162.             inUpButton: 
  163.                 vscroll(GetCtlValue(glob^^.vscr), 1);
  164.             inDownButton: 
  165.                 vscroll(GetCtlValue(glob^^.vscr), -1);
  166.             otherwise
  167.         end;
  168.     end;
  169.  
  170. function inContentHandler (var e: EventRecord): boolean;
  171.     var
  172.         p: MWHndl;
  173.         c: ControlHandle;
  174.         pa, i: integer;
  175.     begin
  176.         p := EvtMW(e);
  177.         if p <> nil then begin
  178.             glob := p;
  179.             GlobalToLocal(e.where);
  180.             pa := FindControl(e.where, p^^.w, c);
  181.             case pa of
  182.                 inUpButton, inDownButton, inPageUp, inPageDown: 
  183.                     if c = p^^.vscr then
  184.                         pa := TrackControl(c, e.where, @Vscrolling);
  185.                 inThumb: 
  186.                     if c = p^^.vscr then begin
  187.                         i := GetCtlValue(c);
  188.                         pa := TrackControl(c, e.where, nil);
  189.                         if pa = inThumb then
  190.                             vscroll(i, i - GetCtlValue(c));
  191.                     end;
  192.                 otherwise
  193.                     if PtInRect(e.where, p^^.t^^.viewRect) then
  194.                         TEClick(e.where, bitand(e.modifiers, ShiftKey) <> 0, p^^.t);
  195.             end;
  196.             inContentHandler := true;
  197.         end
  198.         else
  199.             inContentHandler := false;
  200.     end;
  201.  
  202. function inGrowHandler (var e: EventRecord): boolean;
  203.     var
  204.         p: MWHndl;
  205.         r: Rect;
  206.         ii: longint;
  207.     begin
  208.         p := EvtMW(e);
  209.         if p <> nil then begin
  210.             SetRect(r, 32, 32, 32767, 32767);
  211.             ii := GrowWindow(p^^.w, e.where, r);
  212.             inGrowHandler := true;
  213.             if ii <> 0 then
  214.                 with p^^.w^.portBits.bounds do
  215.                     SetWDimen(p, -left, -top, LoWord(ii), HiWord(ii), inZoomIn);
  216.         end
  217.         else
  218.             inGrowHandler := false;
  219.     end;
  220.  
  221. procedure XCALL (w: WindowPtr; p: ProcPtr);
  222. inline
  223.     $205F, $4E90;        { movea.l (a7)+,a0; jsr (a0) }
  224.  
  225. function inGoAwayHandler (var e: EventRecord): boolean;
  226.     var
  227.         p: MWHndl;
  228.     begin
  229.         p := EvtMW(e);
  230.         if p <> nil then begin
  231.             if TrackGoAway(p^^.w, e.where) then
  232.                 if p^^.whenDone <> nil then
  233.                     XCALL(p^^.w, p^^.whenDone);
  234.             inGoAwayHandler := true;
  235.         end
  236.         else
  237.             inGoAwayHandler := false;
  238.     end;
  239.  
  240. {$IFC ZOOM}
  241. function inZoomInOutHandler (var e: EventRecord): boolean;
  242.     var
  243.         p: MWHndl;
  244.         l, t, w, h: integer;
  245.     begin
  246.         p := EvtMW(e);
  247.         if p <> nil then begin
  248.             if TrackBox(p^^.w, e.where, e.what - mouseMsg) then begin
  249.                 HideWindow(p^^.w);
  250.                 ZoomWindow(p^^.w, e.what - mouseMsg, false);
  251.                 with p^^.w^.portBits.bounds do begin
  252.                     l := -left;
  253.                     t := -top
  254.                 end;
  255.                 with p^^.w^.portRect do begin
  256.                     w := right;
  257.                     h := bottom
  258.                 end;
  259.                 SetWDimen(p, l, t, w, h, e.what - mouseMsg);
  260.                 inZoomInOutHandler := true;
  261.             end
  262.         end
  263.         else
  264.             inZoomInOutHandler := false;
  265.     end;
  266. {$ENDC}
  267.  
  268. function updateHandler (var e: EventRecord): boolean;
  269.     var
  270.         p: MWHndl;
  271.     begin
  272.         flood := 0;
  273.         p := EvtMW(e);
  274.         if p <> nil then begin
  275.             BeginUpdate(p^^.w);
  276.             DrawControls(p^^.w);
  277.             TEUpdate(p^^.w^.portRect, p^^.t);
  278.             DrawGrowIcon(p^^.w);
  279.             EndUpdate(p^^.w);
  280.             updateHandler := true;
  281.         end
  282.         else
  283.             updateHandler := false;
  284.     end;
  285.  
  286. function activateHandler (var e: EventRecord): boolean;
  287.     var
  288.         p: MWHndl;
  289.         r: Rect;
  290.         i: integer;
  291.     begin
  292.         activateHandler := false;
  293.         p := EvtMW(e);
  294.         if p <> nil then begin
  295.             if odd(e.modifiers) then begin
  296.                 HiliteControl(p^^.vscr, 0);
  297.                 TEActivate(p^^.t);
  298.                 mwActive := p;
  299.             end
  300.             else begin
  301.                 HiliteControl(p^^.vscr, 255);
  302.                 TEDeactivate(p^^.t);
  303.                 mwActive := nil;
  304.             end;
  305.             with p^^.w^.portRect do
  306.                 SetRect(r, right - 14, bottom - 14, right, bottom);
  307.             EraseRect(r);
  308. {    InvalRect(p^^.w^.portRect);}
  309.             InvalRect(r);
  310.         end
  311.         else
  312.             mwActive := nil;
  313.     end;
  314.  
  315. function editHandler (var e: EventRecord): boolean;
  316.     var
  317.         i: integer;
  318.     begin
  319.         if mwActive <> nil then
  320.             if e.message = 4 then begin
  321.                 TECopy(mwActive^^.t);
  322.                 editHandler := true
  323.             end
  324.             else if e.message = 7 then begin
  325.                 TESetSelect(0, 32767, mwActive^^.t);
  326.                 SetCtlValue(mwActive^^.vscr, 0);
  327.                 editHandler := true
  328.             end
  329.             else
  330.                 editHandler := false
  331.         else
  332.             editHandler := false
  333.     end;
  334.  
  335. procedure ForceUpdate (w: MWHndl);
  336.     var
  337.         ee: EventRecord;
  338.         b: boolean;
  339.         p0: GrafPtr;
  340.     begin
  341.         GetPort(p0);
  342.         SetPort(w^^.w);
  343.         InvalRect(w^^.w^.portRect);
  344.         ee.message := longint(w^^.w);
  345.         b := updateHandler(ee);
  346.         SetPort(p0)
  347.     end;
  348.  
  349.  
  350. procedure InitMsgWindows;
  351.     var
  352.         i: integer;
  353.     begin
  354.         SetRect(cornerstone, 2, 40, 500, 40);
  355.         with screenBits.bounds do
  356.             SetRect(screensize, -left + 2, -top + 30, right - left - 4, bottom - top - 35);
  357.         i := ApplTask(@inContentHandler, mouseMsg + inContent);
  358.         i := ApplTask(@inGrowHandler, mouseMsg + inGrow);
  359.         i := ApplTask(@inGoAwayHandler, mouseMsg + inGoAway);
  360. {$IFC ZOOM}
  361.         i := ApplTask(@inZoomInOutHandler, mouseMsg + inZoomIn);
  362.         i := ApplTask(@inZoomInOutHandler, mouseMsg + inZoomOut);
  363. {$ENDC}
  364.         i := ApplTask(@updateHandler, updateEvt);
  365.         i := ApplTask(@activateHandler, activateEvt);
  366.         i := ApplTask(@editHandler, menuMsg + editMenu);
  367.         mwActive := nil;
  368.         flood := 0;
  369.         MWdefaultFont := monaco;
  370.         MWdefaultSize := 9;
  371.     end;
  372.  
  373. procedure SetFontSize (window: MWHndl; font, size: integer);
  374.     var
  375.         f: FontInfo;
  376.         s: TextStyle;
  377.         s0, s1: integer;
  378.     begin
  379.         TextFont(font);
  380.         TextSize(size);
  381.         GetFontInfo(f);
  382.         with window^^.sty^^.scrpStyleTab[0] do begin
  383.             scrpStartChar := 0;
  384.             scrpHeight := f.descent + f.leading + f.ascent;
  385.             scrpAscent := f.ascent;
  386.             scrpFont := font;
  387.             scrpFace := [];
  388.             scrpSize := size;
  389.             with scrpColor do begin
  390.                 red := 0;
  391.                 green := 0;
  392.                 blue := 0
  393.             end
  394.         end;
  395.         if window^^.vislines = 0 then
  396.             with window^^.w^.portBits.bounds do
  397.                 window^^.vislines := (3 * (bottom - top - 45) div 4) div window^^.sty^^.scrpStyleTab[0].scrpHeight;
  398.         with window^^.w^.portBits.bounds do
  399.             SetWDimen(window, -left, -top, 80 * CharWidth('x') + 22, window^^.vislines * window^^.sty^^.scrpStyleTab[0].scrpHeight + 16, inZoomIn);
  400.         with s do begin
  401.             tsFont := font;
  402.             tsFace := [];
  403.             tsSize := size;
  404.             with tsColor do begin
  405.                 red := 0;
  406.                 green := 0;
  407.                 blue := 0
  408.             end
  409.         end;
  410.         with window^^.t^^ do begin
  411.             s0 := selStart;
  412.             s1 := selEnd
  413.         end;
  414.         TEDeactivate(window^^.t);
  415.         TESetSelect(0, 32767, window^^.t);
  416.         TESetStyle(doFont + doSize, s, true, window^^.t);
  417.         TESetSelect(s0, s1, window^^.t);
  418.     end;
  419.  
  420. function NewMWindow (var Title: string; prefSize: Rect; DoWhenDone: ProcPtr): MWHndl;
  421.     var
  422.         h: MWHndl;
  423.         p0: GrafPtr;
  424.         r: Rect;
  425.         f: FontInfo;
  426. {$IFC ZOOM}
  427.         wp: WindowPeek;
  428.         zs: WStatesHndl;
  429. {$ENDC}
  430.     begin
  431.         if EmptyRect(prefSize) then begin
  432.             r := cornerstone;
  433.             OffsetRect(cornerstone, 8, 16);
  434.         end
  435.         else begin
  436.             r := prefSize;
  437.             if not SectRect(screensize, r, r) then begin
  438.                 r := cornerstone;
  439.                 OffsetRect(cornerstone, 8, 16);
  440.             end
  441.         end;
  442.         h := MWHndl(NewHandle(sizeof(MWRec)));
  443.         if h <> nil then begin
  444. {$IFC ZOOM}
  445.             h^^.w := NewWindow(nil, r, title, false, 8, WindowPtr(-1), true, longint(h));
  446. {$ELSEC}
  447.             h^^.w := NewWindow(nil, r, title, false, 0, WindowPtr(-1), true, longint(h));
  448. {$ENDC}
  449.             if h^^.w <> nil then begin
  450.                 GetPort(p0);
  451.                 SetPort(h^^.w);
  452.                 TextFont(MWDefaultFont);
  453.                 TextSize(MWDefaultSize);
  454.                 if EmptyRect(r) then
  455.                     h^^.vislines := 0
  456.                 else begin
  457.                     GetFontInfo(f);
  458.                     with f do
  459.                         h^^.vislines := (r.bottom - r.top - 16) div (descent + leading + ascent)
  460.                 end;
  461.                 h^^.magic := MW_MAGIC;
  462.                 h^^.hscr := NewControl(h^^.w, r, '', true, 0, 0, 0, 16, 0);
  463.                 h^^.vscr := NewControl(h^^.w, r, '', true, 0, 0, 0, 16, 0);
  464.                 h^^.whenDone := DoWhenDone;
  465.                 h^^.t := TEStylNew(r, r);
  466.                 h^^.sty := stScrpHandle(NewHandle(STY_0));
  467.                 h^^.NumStyles := 0;
  468. {$IFC ZOOM}
  469.                 wp := WindowPeek(h^^.w);
  470.                 zs := WStatesHndl(wp^.dataHandle);
  471.                 with zs^^[inZoomOut] do begin
  472.                     right := right - 64;
  473.                     bottom := bottom - 32;
  474.                 end;
  475. {$ENDC}
  476.                 TEAutoView(false, h^^.t);
  477.                 TEActivate(h^^.t);
  478.                 SetFontSize(h, MWdefaultFont, MWdefaultSize);
  479.                 SetPort(p0)
  480.             end
  481.         end;
  482.         NewMWindow := h
  483.     end;
  484.  
  485.  
  486. procedure DeleteMWindow (window: MWHndl);
  487.     begin
  488.         HideWindow(window^^.w);
  489.         TEDispose(window^^.t);
  490.         DisposeControl(window^^.hscr);
  491.         DisposeControl(window^^.vscr);
  492.         DisposeWindow(window^^.w);
  493.         DisposHandle(Handle(window^^.sty));
  494.         DisposHandle(Handle(window));
  495.     end;
  496.  
  497.  
  498. procedure FreeMW (window: MWHndl);
  499.     begin
  500.         TESetSelect(0, MW_KILLEN, window^^.t);
  501.         TEDelete(window^^.t);
  502. {    i := Munger(Handle(window^^.t^^.hText), 0, nil, MW_KILLEN, ptr(1), 0);}
  503. {    TECalText(window^^.t);}
  504. {    TESelView(window^^.t);}
  505. {    ForceUpdate(window);}
  506.     end;
  507.  
  508. procedure MWMessage (window: MWHndl; var msg: string);
  509.     var
  510.         p0: GrafPtr;
  511.         s0, s1, i, c, nsty: integer;
  512.         s: Style;
  513.         e: EventRecord;
  514.         ndelay: boolean;
  515.  
  516.     procedure AddHunk (y: Style);
  517.         begin
  518.             if y <> s then
  519.                 with window^^ do begin
  520.                     nsty := nsty + 1;
  521.                     if nsty > NumStyles then begin
  522.                         SetHandleSize(Handle(sty), STY_0 + nsty * STY_1);
  523.                         NumStyles := nsty
  524.                     end;
  525.                     with sty^^ do begin
  526.                         scrpStyleTab[nsty] := scrpStyleTab[nsty - 1];
  527.                         scrpStyleTab[nsty].scrpStartChar := i;
  528.                         scrpStyleTab[nsty].scrpFace := y;
  529.                     end;
  530.                     s := y
  531.                 end;
  532.         end;
  533.  
  534.     procedure ToggleHunk (x: StyleItem);
  535.         begin
  536.             if x in s then
  537.                 AddHunk(s - [x])
  538.             else
  539.                 AddHunk(s + [x])
  540.         end;
  541.  
  542.     begin
  543.         if window <> nil then begin
  544.             ndelay := EventAvail(everyEvent, e);
  545.             ndelay := (BitAnd(e.modifiers, shiftKey) = 0);
  546.             GetPort(p0);
  547.             SetPort(window^^.w);
  548.             with window^^.t^^ do begin
  549.                 s0 := selStart;
  550.                 s1 := selEnd
  551.             end;
  552.             TEDeactivate(window^^.t);
  553.             if window^^.t^^.teLength > MW_MAXLEN then begin
  554.                 FreeMW(window);
  555.                 ndelay := true;
  556.                 s0 := s0 - MW_KILLEN;
  557.                 if s0 < 0 then
  558.                     s0 := 0;
  559.                 s1 := s1 - MW_KILLEN;
  560.                 if s1 < 0 then
  561.                     s1 := 0;
  562.             end;
  563.             if pos(chr(7), msg) > 0 then
  564.                 SysBeep(10);
  565.             s := [];
  566.             nsty := 0;
  567.             i := 1;
  568.             while i <= length(msg) do begin
  569.                 c := ord(msg[i]);
  570.                 if c < 32 then begin
  571.                     case c of
  572.                         C_BOLD: 
  573.                             ToggleHunk(bold);
  574.                         C_UNDERLINE: 
  575.                             ToggleHunk(underline);
  576.                         C_INVERSE: 
  577.                             ToggleHunk(outline);
  578.                         C_NORMAL: 
  579.                             AddHunk([]);
  580.                         otherwise
  581.                     end;
  582.                     delete(msg, i, 1);
  583.                 end;
  584.                 i := i + 1;
  585.             end;
  586.             insert(chr(13), msg, 1);
  587.             TESetSelect(32767, 32767, window^^.t);
  588.             window^^.sty^^.scrpNStyles := nsty + 1;
  589.             TEStylInsert(@msg[1], length(msg), window^^.sty, window^^.t);
  590.             if ndelay then begin
  591.                 TEAutoView(true, window^^.t);
  592.                 TESelView(window^^.t);
  593.                 TEAutoView(false, window^^.t);
  594.             end;
  595.             TESetSelect(s0, s1, window^^.t);
  596.             if window^^.w = FrontWindow then
  597.                 TEActivate(window^^.t);
  598.             i := window^^.t^^.nlines - window^^.vislines + 1;
  599.             if i < 0 then
  600.                 i := 0;
  601.             SetCtlMax(window^^.vscr, i);
  602.             if ndelay then
  603.                 SetCtlValue(window^^.vscr, i);
  604. {    InvalRect(window^^.t^^.viewRect);}
  605.             SetPort(p0);
  606.         end;
  607.     end;
  608.  
  609. { by now it's a dummy :-) }
  610. function MWFreeMem: boolean;
  611.     begin
  612.         MWFreeMem := false;
  613.     end;
  614.  
  615. end.